package com.windy.kafka.sender.annotation.interceptor;

import com.windy.kafka.sender.annotation.annotation.MessageSender;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.interceptor.AsyncExecutionInterceptor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;

/**
 * Created by liyufeng on 2022/3/22
 */
//todo添加同步模型
public class AnnotationMessageExecutionInterceptor extends AsyncExecutionInterceptor {

    private KafkaTemplate<Integer, Object> kafkaTemplate;

    protected BeanFactory beanFactory;

    public AnnotationMessageExecutionInterceptor(KafkaTemplate<Integer, Object> kafkaTemplate) {
        super(null,null);
        this.kafkaTemplate = kafkaTemplate;
    }

    @Override
    @Nullable
    protected String getExecutorQualifier(Method method) {
        // Maintainer's note: changes made here should also be made in
        // AnnotationAsyncExecutionAspect#getExecutorQualifier
        MessageSender async = AnnotatedElementUtils.findMergedAnnotation(method, MessageSender.class);
        if (async == null) {
            async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), MessageSender.class);
        }
        return (async != null ? async.value() : null);
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        Class<?> targetClass = getTargetClass(invocation.getThis());
        Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
        // If we are dealing with method with generic parameters, find the original method.
        specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
        MessageSender mergedAnnotation = AnnotatedElementUtils.getMergedAnnotation(specificMethod, MessageSender.class);
        Object result = invocation.proceed();
        //value如何界定  EL 表达式？
        // todo ,暂时拿response
        kafkaTemplate.send(mergedAnnotation.topic(), result);
        return result;

    }

    private Class<?> getTargetClass(Object target) {
        return AopProxyUtils.ultimateTargetClass(target);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

}
